import subprocess
from datetime import datetime

from rest_framework import status
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet
from rest_framework.filters import OrderingFilter, SearchFilter
from django_filters.rest_framework import DjangoFilterBackend

from app.models import City, MachineRoom, Host
from app.serializers import CityModelSerializer, MachineRoomModelSerializer, HosModelSerializer


# Create your views here.

class CityModelViewSet(ModelViewSet):
    queryset = City.objects.all()
    serializer_class = CityModelSerializer
    filter_backends = [OrderingFilter, SearchFilter]
    search_fields = ['name']
    ordering_fields = ['name', 'created_at']


class MachineModelViewSet(ModelViewSet):
    queryset = MachineRoom.objects.all()
    serializer_class = MachineRoomModelSerializer
    filter_backends = [DjangoFilterBackend, SearchFilter]
    search_fields = ['name']
    filterset_fields = ['city']


class HostModelViewSet(ModelViewSet):
    queryset = Host.objects.all()
    serializer_class = HosModelSerializer
    filter_backends = [DjangoFilterBackend, SearchFilter]
    filterset_fields = ['city', 'machine', 'is_ping']
    search_fields = ['hostname', 'ip_address']

    @action(detail=False, methods=["post"], url_path="ping")
    def ping_result(self, request):
        """执行 ping """
        ip_address = request.data['ip_address']
        if not ip_address:
            raise ValueError("未提供主机 IP 地址")

        try:
            # 发送2个ICMP包，超时2秒
            result = subprocess.run(
                ["ping", "-c", "2", "-W", "2", ip_address],
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                text=True
            )

            is_reachable = result.returncode == 0
            host = Host.objects.get(ip_address=ip_address)
            if host:
                host.is_ping = is_reachable
                host.last_ping_time = datetime.now()
                host.save(update_fields=["is_ping", "last_ping_time"])

            return Response({
                "ip_address": ip_address,
                "reachable": is_reachable,
                "timestamp": datetime.now().isoformat(),
            })

        except subprocess.TimeoutExpired:
            return Response(
                {"error": f"Ping {ip_address} 超时（超过10秒）"},
                status=status.HTTP_504_GATEWAY_TIMEOUT
            )

        except Exception as e:
            return Response(
                {"error": f"Ping探测失败: {str(e)}"},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )
